﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.ComponentModel;
using System.Globalization;
using System.Security.Principal;
using System.Collections.Generic;

using SBPweb.Localization;

using SBPweb.Modules.Communication;
using SBPweb.Modules.Modularity;
using SBPweb.Modules.Smartparts;
using SBPweb.Modules.Logging;

using SBPweb.Presentation.Windows.WPF.Controls;

using SBPweb.Presentation.Windows.WPF.Host.Controls;

namespace SBPweb.Presentation.Windows.WPF.Host
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IModuleHost
    {

        private IMenuList pMainMenu;
        private IMessageQueue pMessageQueue;
        private ISmartpartList pSmartpartList;
        private IPrincipal pPrincipal;
        private Vector3D pCamFrom;
        private Vector3D pCamTo;

        private double pCamDepth = 2600;

        private Dictionary<UserControl, _3DTools.InteractiveVisual3D> pDictOfVisuals;

        private static ILogManager pLogManager;


        public MainWindow()
        {
            InitializeComponent();

            pMainMenu = new CarouselMenu();
            pSmartpartList = new SmartpartList();
            pDictOfVisuals = new Dictionary<UserControl, _3DTools.InteractiveVisual3D>();

            pMainMenu.ItemAdded += new EventHandler<MenuEventArgs>(pMainMenu_OnAdded);
            pMainMenu.ItemRemoved += new EventHandler<MenuEventArgs>(pMainMenu_OnRemoved);

            pSmartpartList.ItemAdded += new EventHandler<SmartpartEventArgs>(pSmartpartList_OnAdded);
            pSmartpartList.ItemRemoved += new EventHandler<SmartpartEventArgs>(pSmartpartList_OnRemoved);

            this.AddHandler(Window.KeyDownEvent, new KeyEventHandler(MainWindow_KeyDown), true);
            this.AddHandler(Window.MouseWheelEvent, new MouseWheelEventHandler(MainWindow_MouseWheel), true);
        }

        void pSmartpartList_OnAdded(object sender, SmartpartEventArgs e)
        {
            if (e.Smartpart is UserControl3D)
            {
                UserControl3D userControl = e.Smartpart as UserControl3D;
                MeshGeometry3D geom3d = (TryFindResource("PlaneMesh") as MeshGeometry3D).Clone();

//                _3DTools.InteractiveVisual3D iv3d = new InteractiveCylinder();
                _3DTools.InteractiveVisual3D iv3d = new _3DTools.InteractiveVisual3D();

                iv3d.IsBackVisible = true;
                iv3d.Geometry = geom3d;
                iv3d.Visual = userControl;

                pDictOfVisuals.Add(userControl, iv3d);
                viewport.Children.Add(iv3d);

                userControl.TranslationChanged += new EventHandler(userControl_TranslationChanged);
                TransformInteractiveVisualUserControl(userControl);
            }
        }

        void userControl_TranslationChanged(object sender, EventArgs e)
        {
            TransformInteractiveVisualUserControl(sender as UserControl3D);
        }

        void pSmartpartList_OnRemoved(object sender, SmartpartEventArgs e)
        {

        }

        void pMainMenu_OnAdded(object sender, MenuEventArgs e)
        {
        }

        void pMainMenu_OnRemoved(object sender, MenuEventArgs e)
        {
        }

        void MainWindow_KeyDown(object sender, KeyEventArgs e)
        {
            double angleX = 0.0;
            double angleY = 0.0;
            switch (e.Key)
            {
                default:
                    return;
                case Key.Left:
                    angleX = 0.1;
                    break;
                case Key.Right:
                    angleX = -0.1;
                    break;
                case Key.Down:
                    angleY = -0.1;
                    break;
                case Key.Up:
                    angleY = 0.1;
                    break;
            }

            PerspectiveCamera cam = viewport.Camera as PerspectiveCamera;
            RegisterName("camera", cam);

            if (pCamFrom == null || pCamFrom == new Vector3D(0,0,0))
            {
                pCamFrom = cam.LookDirection;
            }
            pCamTo = Vector3D.Add(pCamFrom, new Vector3D(angleX, angleY, 0));
            Timeline anim = new Vector3DAnimation(pCamFrom, pCamTo, new Duration(new TimeSpan(0, 0, 0, 0, 100)));
            Storyboard s = new Storyboard();
            s.Children.Add(anim);

            Storyboard.SetTargetName(anim, "camera");
            Storyboard.SetTargetProperty(anim, new PropertyPath(PerspectiveCamera.LookDirectionProperty));

            s.Begin(this);
            pCamFrom = pCamTo;
        }

        void MainWindow_MouseWheel(object sender, MouseWheelEventArgs e)
        {
        }

        #region IModuleHost Members

        public IMenuList Menu
        {
            get
            {
                return pMainMenu;
            }
        }

        public IMessageQueue Messages
        {
            get
            {
                return pMessageQueue;
            }
        }

        public ISmartpartList Smartparts
        {
            get
            {
                return pSmartpartList;
            }
        }

        public IMenuList StatusBar
        {
            get { throw new NotImplementedException(); }
        }

        public ILogManager LogManager
        {
            get
            {
                if (pLogManager == null)
                {
                    pLogManager = new LogManager();
                }
                return pLogManager;
            }
        }

        public IPrincipal SecurityPrincipal
        {
            get
            {
                return pPrincipal;
            }
            set
            {
                pPrincipal = value;
            }
        }

        public CultureInfo[] SupportedCultures
        {
            get
            {
                return App.SUPPORTED_CULTURES;
            }
        }

        public void SetCulture(System.Globalization.CultureInfo ci)
        {
            ResourceHandler.SetCurrentCulture(ci);
            LocalizationExtender.Culture = ci;
        }

		public ModuleLoader ModuleLoader
		{
			get 
			{
				return App.Loader;
			}
		}

		public ModuleHostType HostType
		{
			get
			{
				return ModuleHostType.WindowsPresentationFoundation;
			}
		}

        public event EventHandler OnApplicationClosing;

        #endregion

        void TransformInteractiveVisualUserControl(UserControl3D userControl)
        {
            _3DTools.InteractiveVisual3D iv3d = null;
            PerspectiveCamera camera = viewport.Camera as PerspectiveCamera;
            if (pDictOfVisuals.ContainsKey(userControl))
            {
                iv3d = pDictOfVisuals[userControl];
            }

            if (iv3d == null)
            {
                return;
            }

            Point3D startPoint = camera.Position;
            Vector3D vectTrans = new Vector3D(0, 0, pCamDepth + userControl.Position.Z);
            Vector3D vectScale = new Vector3D(-1.0 * userControl.Size.Width, userControl.Size.Height, 1);

            double boundary = 2 * pCamDepth * Math.PI;
            double click = boundary / 360.0;
            double alphaX = Math.Asin(userControl.Position.X / (pCamDepth + userControl.Position.Z)) * click * 3;
            double alphaY = Math.Asin(userControl.Position.Y / (pCamDepth + userControl.Position.Z)) * click * 3;

//            vectRot = Vector3D.Add(vectRot, new Vector3D(userControl.Position.X * degree, -1.0 * userControl.Position.Y * degree, userControl.Position.Z * degree));

//            Point3D p = Vector3D.Add(vectRot, userControl.Position);



            Matrix3D trix = new Matrix3D();
            trix.Append(new ScaleTransform3D(vectScale).Value);
            trix.Append(new TranslateTransform3D(vectTrans).Value);
            trix.Append(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, -1, 0), alphaX), startPoint).Value);
            trix.Append(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1, 0, 0), alphaY), startPoint).Value);
            iv3d.Transform = new MatrixTransform3D(trix);
        }

		#region IModuleHost Members

		public ILayoutProvider LayoutProvider
		{
			get 
			{
				return null;
			}
		}

		#endregion

		#region IPersistable Members

		public string PersistencyKey
		{
			get
			{
				return this.GetType().Name;
			}
		}

		public IPersistable ParentPersistable
		{
			get
			{
				return null;
			}

		}

		#endregion
	}
}
